package com.tang.module.rabbitmq.notice.service.impl;

import cn.hutool.core.map.MapUtil;
import com.alibaba.fastjson2.JSON;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.sun.jna.NativeLong;
import com.tang.module.notice.entity.Notice;
import com.tang.module.notice.entity.NoticeEnum;
import com.tang.module.notice.entity.NoticeLog;
import com.tang.module.notice.mapper.NoticeLogMapper;
import com.tang.module.notice.mapper.NoticeMapper;
import com.tang.module.rabbitmq.notice.config.NoticeDefinition;
import com.tang.module.rabbitmq.notice.service.NoticeRabbitService;
import com.tang.module.system.entity.User;
import com.tang.module.system.service.UserService;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * 系统通知的rabbitMQ业务层实现类
 * @author 月蚀
 * @since 2022/6/16 16:16
 */
@Service("noticeRabbitService")
public class NoticeRabbitServiceImpl implements NoticeRabbitService {

    @Resource
    private RabbitTemplate rabbitTemplate;

    @Resource
    private NoticeMapper noticeMapper;

    @Resource
    private NoticeLogMapper noticeLogMapper;

    @Resource
    private UserService userService;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean byUserIdSend(Long uid,  String title, String message) {
        //保存消息日志
        NoticeLog noticeLog = new NoticeLog();
        noticeLog.setTitle(title).setMessage(message).setReceiveUser(uid).setType(NoticeEnum.ONE.getCode());
        noticeLogMapper.insert(noticeLog);
        //发送消息
        sendAndSaveNative(uid, title, message, noticeLog);
        return true;

    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean bulkSend(List<Long> deptList, String title, String message) {
        //保存消息日志
        NoticeLog noticeLog = new NoticeLog();
        noticeLog.setTitle(title).setMessage(message).
                //将部门id计划转换为逗号分割的字符串
                setReceiveGroup(deptList.stream().map(Long::toUnsignedString).collect(Collectors.joining(","))).setType(NoticeEnum.ONE.getCode());
        noticeLogMapper.insert(noticeLog);
        //循环出每个部门
        for (Long deptId : deptList) {
            //找出该部门全部员工
            List<User> users = userService.list(Wrappers.<User>lambdaQuery().select(User::getId).eq(User::getDeptId, deptId));
            Set<Long> ids = users.stream().map(User::getId).collect(Collectors.toSet());
            for (Long uid : ids) {
                sendAndSaveNative(uid,title,message,noticeLog);
            }
        }
        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean byUsersIdSend(List<Long> uidList, String title, String message) {
        //保存消息日志
        NoticeLog noticeLog = new NoticeLog();
        noticeLog.setTitle(title).setMessage(message).
                setReceiveGroup(uidList.stream().map(Long::toUnsignedString).collect(Collectors.joining(","))).setType(NoticeEnum.ONE.getCode());
        noticeLogMapper.insert(noticeLog);
        //循环发送数据和保存数据到数据库
        for (Long uid : uidList) {
            sendAndSaveNative(uid,title,message,noticeLog);
        }
        return true;
    }

    /**
     * 发送消息，并且保存消息到消息到数据库
     * @param uid 用户id
     * @param title 消息标题
     * @param message 消息内容
     * @param noticeLog 本次消息日志
     */
    private void sendAndSaveNative(Long uid, String title, String message, NoticeLog noticeLog) {
        Notice notice = new Notice();
        notice.setLogId(noticeLog.getId()).setReceiveUser(uid).setTitle(title).setMessage(message).
                setType(NoticeEnum.ONE.getCode()).setCreateTime(notice.getCreateTime());
        noticeMapper.insert(notice);
        //发送消息
        rabbitTemplate.convertAndSend(NoticeDefinition.SYSTEM_NOTICE_EXCHANGE, String.valueOf(uid),
                JSON.toJSONString(MapUtil.builder().put("title", title).put("message", message).build()));
    }


}
